// META: title=test WebNN API elu operation
// META: global=window,dedicatedworker
// META: variant=?cpu
// META: variant=?gpu
// META: variant=?npu
// META: script=../resources/utils.js
// META: timeout=long

'use strict';

// https://www.w3.org/TR/webnn/#api-mlgraphbuilder-elu
// Calculate the exponential linear unit function (ELU) on the input tensor
// element-wise. The calculation follows the expression
// max(0, x) + alpha * (exp(min(0, x)) - 1).
//
// dictionary MLEluOptions {
//   double alpha = 1;
// };
//
// MLOperand elu(MLOperand input, optional MLEluOptions options = {});


const getEluPrecisionTolerance = (graphResources) => {
  const toleranceValueDict = {float32: 18, float16: 18};
  const expectedDataType =
      getExpectedDataTypeOfSingleOutput(graphResources.expectedOutputs);
  return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]};
};

const eluTests = [
  {
    'name': 'elu float32 positive 0D scalar default options',
    'graph': {
      'inputs': {
        'eluInput': {
          'data': [4.721739768981934],
          'descriptor': {'dimensions': [], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'elu',
        'arguments': [{'input': 'eluInput'}],
        'outputs': 'eluOutput'
      }],
      'expectedOutputs': {
        'eluOutput': {
          'data': [4.721739768981934],
          'descriptor': {'dimensions': [], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'elu float32 negative 0D scalar default options',
    'graph': {
      'inputs': {
        'eluInput': {
          'data': [-3.8663666248321533],
          'descriptor': {'dimensions': [], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'elu',
        'arguments': [{'input': 'eluInput'}],
        'outputs': 'eluOutput'
      }],
      'expectedOutputs': {
        'eluOutput': {
          'data': [-0.9790657162666321],
          'descriptor': {'dimensions': [], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'elu float32 1D constant tensor default options',
    'graph': {
      'inputs': {
        'eluInput': {
          'data': [
            4.721739768981934,   0.3768780529499054, 1.4189997911453247,
            -3.8663666248321533, 1.3590080738067627, -3.8641843795776367,
            7.839725494384766,   -6.69080114364624,  0.5456406474113464,
            5.776711463928223,   7.263273239135742,  -7.419948101043701,
            5.665064334869385,   -6.712906837463379, -3.334894895553589,
            -1.2103675603866577, 7.255547046661377,  8.903468132019043,
            -4.01986026763916,   7.114678382873535,  -0.11212847381830215,
            -3.688840866088867,  6.135150909423828,  -9.895182609558105
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'},
          'constant': true
        }
      },
      'operators': [{
        'name': 'elu',
        'arguments': [{'input': 'eluInput'}],
        'outputs': 'eluOutput'
      }],
      'expectedOutputs': {
        'eluOutput': {
          'data': [
            4.721739768981934,   0.3768780529499054,  1.4189997911453247,
            -0.9790657162666321, 1.3590080738067627,  -0.9790199995040894,
            7.839725494384766,   -0.9987577199935913, 0.5456406474113464,
            5.776711463928223,   7.263273239135742,   -0.999400794506073,
            5.665064334869385,   -0.9987848997116089, -0.9643816947937012,
            -0.7019122838973999, 7.255547046661377,   8.903468132019043,
            -0.982044517993927,  7.114678382873535,   -0.10607059299945831,
            -0.9749990105628967, 6.135150909423828,   -0.99994957447052
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'elu float32 1D tensor default options',
    'graph': {
      'inputs': {
        'eluInput': {
          'data': [
            4.721739768981934,   0.3768780529499054, 1.4189997911453247,
            -3.8663666248321533, 1.3590080738067627, -3.8641843795776367,
            7.839725494384766,   -6.69080114364624,  0.5456406474113464,
            5.776711463928223,   7.263273239135742,  -7.419948101043701,
            5.665064334869385,   -6.712906837463379, -3.334894895553589,
            -1.2103675603866577, 7.255547046661377,  8.903468132019043,
            -4.01986026763916,   7.114678382873535,  -0.11212847381830215,
            -3.688840866088867,  6.135150909423828,  -9.895182609558105
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'elu',
        'arguments': [{'input': 'eluInput'}],
        'outputs': 'eluOutput'
      }],
      'expectedOutputs': {
        'eluOutput': {
          'data': [
            4.721739768981934,   0.3768780529499054,  1.4189997911453247,
            -0.9790657162666321, 1.3590080738067627,  -0.9790199995040894,
            7.839725494384766,   -0.9987577199935913, 0.5456406474113464,
            5.776711463928223,   7.263273239135742,   -0.999400794506073,
            5.665064334869385,   -0.9987848997116089, -0.9643816947937012,
            -0.7019122838973999, 7.255547046661377,   8.903468132019043,
            -0.982044517993927,  7.114678382873535,   -0.10607059299945831,
            -0.9749990105628967, 6.135150909423828,   -0.99994957447052
          ],
          'descriptor': {'dimensions': [24], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'elu float32 2D tensor default options',
    'graph': {
      'inputs': {
        'eluInput': {
          'data': [
            4.721739768981934,   0.3768780529499054, 1.4189997911453247,
            -3.8663666248321533, 1.3590080738067627, -3.8641843795776367,
            7.839725494384766,   -6.69080114364624,  0.5456406474113464,
            5.776711463928223,   7.263273239135742,  -7.419948101043701,
            5.665064334869385,   -6.712906837463379, -3.334894895553589,
            -1.2103675603866577, 7.255547046661377,  8.903468132019043,
            -4.01986026763916,   7.114678382873535,  -0.11212847381830215,
            -3.688840866088867,  6.135150909423828,  -9.895182609558105
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'elu',
        'arguments': [{'input': 'eluInput'}],
        'outputs': 'eluOutput'
      }],
      'expectedOutputs': {
        'eluOutput': {
          'data': [
            4.721739768981934,   0.3768780529499054,  1.4189997911453247,
            -0.9790657162666321, 1.3590080738067627,  -0.9790199995040894,
            7.839725494384766,   -0.9987577199935913, 0.5456406474113464,
            5.776711463928223,   7.263273239135742,   -0.999400794506073,
            5.665064334869385,   -0.9987848997116089, -0.9643816947937012,
            -0.7019122838973999, 7.255547046661377,   8.903468132019043,
            -0.982044517993927,  7.114678382873535,   -0.10607059299945831,
            -0.9749990105628967, 6.135150909423828,   -0.99994957447052
          ],
          'descriptor': {'dimensions': [4, 6], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'elu float32 3D tensor default options',
    'graph': {
      'inputs': {
        'eluInput': {
          'data': [
            4.721739768981934,   0.3768780529499054, 1.4189997911453247,
            -3.8663666248321533, 1.3590080738067627, -3.8641843795776367,
            7.839725494384766,   -6.69080114364624,  0.5456406474113464,
            5.776711463928223,   7.263273239135742,  -7.419948101043701,
            5.665064334869385,   -6.712906837463379, -3.334894895553589,
            -1.2103675603866577, 7.255547046661377,  8.903468132019043,
            -4.01986026763916,   7.114678382873535,  -0.11212847381830215,
            -3.688840866088867,  6.135150909423828,  -9.895182609558105
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'elu',
        'arguments': [{'input': 'eluInput'}],
        'outputs': 'eluOutput'
      }],
      'expectedOutputs': {
        'eluOutput': {
          'data': [
            4.721739768981934,   0.3768780529499054,  1.4189997911453247,
            -0.9790657162666321, 1.3590080738067627,  -0.9790199995040894,
            7.839725494384766,   -0.9987577199935913, 0.5456406474113464,
            5.776711463928223,   7.263273239135742,   -0.999400794506073,
            5.665064334869385,   -0.9987848997116089, -0.9643816947937012,
            -0.7019122838973999, 7.255547046661377,   8.903468132019043,
            -0.982044517993927,  7.114678382873535,   -0.10607059299945831,
            -0.9749990105628967, 6.135150909423828,   -0.99994957447052
          ],
          'descriptor': {'dimensions': [2, 3, 4], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'elu float32 4D tensor default options',
    'graph': {
      'inputs': {
        'eluInput': {
          'data': [
            4.721739768981934,   0.3768780529499054, 1.4189997911453247,
            -3.8663666248321533, 1.3590080738067627, -3.8641843795776367,
            7.839725494384766,   -6.69080114364624,  0.5456406474113464,
            5.776711463928223,   7.263273239135742,  -7.419948101043701,
            5.665064334869385,   -6.712906837463379, -3.334894895553589,
            -1.2103675603866577, 7.255547046661377,  8.903468132019043,
            -4.01986026763916,   7.114678382873535,  -0.11212847381830215,
            -3.688840866088867,  6.135150909423828,  -9.895182609558105
          ],
          'descriptor': {'dimensions': [1, 2, 3, 4], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'elu',
        'arguments': [{'input': 'eluInput'}],
        'outputs': 'eluOutput'
      }],
      'expectedOutputs': {
        'eluOutput': {
          'data': [
            4.721739768981934,   0.3768780529499054,  1.4189997911453247,
            -0.9790657162666321, 1.3590080738067627,  -0.9790199995040894,
            7.839725494384766,   -0.9987577199935913, 0.5456406474113464,
            5.776711463928223,   7.263273239135742,   -0.999400794506073,
            5.665064334869385,   -0.9987848997116089, -0.9643816947937012,
            -0.7019122838973999, 7.255547046661377,   8.903468132019043,
            -0.982044517993927,  7.114678382873535,   -0.10607059299945831,
            -0.9749990105628967, 6.135150909423828,   -0.99994957447052
          ],
          'descriptor': {'dimensions': [1, 2, 3, 4], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'elu float32 5D tensor default options',
    'graph': {
      'inputs': {
        'eluInput': {
          'data': [
            4.721739768981934,   0.3768780529499054, 1.4189997911453247,
            -3.8663666248321533, 1.3590080738067627, -3.8641843795776367,
            7.839725494384766,   -6.69080114364624,  0.5456406474113464,
            5.776711463928223,   7.263273239135742,  -7.419948101043701,
            5.665064334869385,   -6.712906837463379, -3.334894895553589,
            -1.2103675603866577, 7.255547046661377,  8.903468132019043,
            -4.01986026763916,   7.114678382873535,  -0.11212847381830215,
            -3.688840866088867,  6.135150909423828,  -9.895182609558105
          ],
          'descriptor': {'dimensions': [1, 2, 1, 3, 4], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'elu',
        'arguments': [{'input': 'eluInput'}],
        'outputs': 'eluOutput'
      }],
      'expectedOutputs': {
        'eluOutput': {
          'data': [
            4.721739768981934,   0.3768780529499054,  1.4189997911453247,
            -0.9790657162666321, 1.3590080738067627,  -0.9790199995040894,
            7.839725494384766,   -0.9987577199935913, 0.5456406474113464,
            5.776711463928223,   7.263273239135742,   -0.999400794506073,
            5.665064334869385,   -0.9987848997116089, -0.9643816947937012,
            -0.7019122838973999, 7.255547046661377,   8.903468132019043,
            -0.982044517993927,  7.114678382873535,   -0.10607059299945831,
            -0.9749990105628967, 6.135150909423828,   -0.99994957447052
          ],
          'descriptor': {'dimensions': [1, 2, 1, 3, 4], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'elu float32 4D tensor positive options.alpha',
    'graph': {
      'inputs': {
        'eluInput': {
          'data': [
            4.721739768981934,   0.3768780529499054, 1.4189997911453247,
            -3.8663666248321533, 1.3590080738067627, -3.8641843795776367,
            7.839725494384766,   -6.69080114364624,  0.5456406474113464,
            5.776711463928223,   7.263273239135742,  -7.419948101043701,
            5.665064334869385,   -6.712906837463379, -3.334894895553589,
            -1.2103675603866577, 7.255547046661377,  8.903468132019043,
            -4.01986026763916,   7.114678382873535,  -0.11212847381830215,
            -3.688840866088867,  6.135150909423828,  -9.895182609558105
          ],
          'descriptor': {'dimensions': [1, 2, 3, 4], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'elu',
        'arguments':
            [{'input': 'eluInput'}, {'options': {'alpha': 0.3607245505146506}}],
        'outputs': 'eluOutput'
      }],
      'expectedOutputs': {
        'eluOutput': {
          'data': [
            4.721739768981934,    0.3768780529499054,   1.4189997911453247,
            -0.35317301750183105, 1.3590080738067627,   -0.35315653681755066,
            7.839725494384766,    -0.36027640104293823, 0.5456406474113464,
            5.776711463928223,    7.263273239135742,    -0.36050841212272644,
            5.665064334869385,    -0.3602862060070038,  -0.3478761315345764,
            -0.25319698452949524, 7.255547046661377,    8.903468132019043,
            -0.3542475700378418,  7.114678382873535,    -0.0382622666656971,
            -0.3517060875892639,  6.135150909423828,    -0.3607063591480255
          ],
          'descriptor': {'dimensions': [1, 2, 3, 4], 'dataType': 'float32'}
        }
      }
    }
  },
  {
    'name': 'elu float32 4D tensor negative options.alpha',
    'graph': {
      'inputs': {
        'eluInput': {
          'data': [
            4.721739768981934,   0.3768780529499054, 1.4189997911453247,
            -3.8663666248321533, 1.3590080738067627, -3.8641843795776367,
            7.839725494384766,   -6.69080114364624,  0.5456406474113464,
            5.776711463928223,   7.263273239135742,  -7.419948101043701,
            5.665064334869385,   -6.712906837463379, -3.334894895553589,
            -1.2103675603866577, 7.255547046661377,  8.903468132019043,
            -4.01986026763916,   7.114678382873535,  -0.11212847381830215,
            -3.688840866088867,  6.135150909423828,  -9.895182609558105
          ],
          'descriptor': {'dimensions': [1, 2, 3, 4], 'dataType': 'float32'}
        }
      },
      'operators': [{
        'name': 'elu',
        'arguments':
            [{'input': 'eluInput'}, {'options': {'alpha': -3.468180406374035}}],
        'outputs': 'eluOutput'
      }],
      'expectedOutputs': {
        'eluOutput': {
          'data': [
            4.721739768981934,  0.3768780529499054, 1.4189997911453247,
            3.3955764770507812, 1.3590080738067627, 3.3954179286956787,
            7.839725494384766,  3.463871955871582,  0.5456406474113464,
            5.776711463928223,  7.263273239135742,  3.466102361679077,
            5.665064334869385,  3.463966131210327,  3.34464955329895,
            2.434358596801758,  7.255547046661377,  8.903468132019043,
            3.40590763092041,   7.114678382873535,  0.3678719699382782,
            3.381472587585449,  6.135150909423828,  3.468005657196045
          ],
          'descriptor': {'dimensions': [1, 2, 3, 4], 'dataType': 'float32'}
        }
      }
    }
  }
];

if (navigator.ml) {
  eluTests.forEach((test) => {
    webnn_conformance_test(
        buildGraphAndCompute, getEluPrecisionTolerance, test);
  });
} else {
  test(() => assert_implements(navigator.ml, 'missing navigator.ml'));
}
